﻿

#include <windows.h>
#include <winioctl.h>
#include <virtdisk.h>
#include <stdio.h>
#include <time.h>

#pragma comment(lib, "VirtDisk.lib")

BOOL GetDriveGeometry(LPCWSTR strPath, DISK_GEOMETRY* pdg)

{
    HANDLE hDevice; // handle to the drive to be examined
    BOOL bResult; // results flag
    DWORD junk; // discard results

    hDevice = CreateFile(strPath, // drive
        0, // no access to the drive
        FILE_SHARE_READ | // share mode
        FILE_SHARE_WRITE,
        NULL, // default security attributes
        OPEN_EXISTING, // disposition
        0, // file attributes
        NULL); // do not copy file attributes

    if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
    {
        return (FALSE);
    }

    bResult = DeviceIoControl(hDevice, // device to be queried
        IOCTL_DISK_GET_DRIVE_GEOMETRY, // operation to perform
        NULL, 0, // no input buffer
        pdg, sizeof(*pdg), // output buffer
        &junk, // # bytes returned
        (LPOVERLAPPED)NULL); // synchronous I/O

    CloseHandle(hDevice);

    return (bResult);

}

DWORD CreateDisk2(DWORD disk, WORD partNum, LPWSTR diskPath)
{
    HANDLE hDevice;               // handle to the drive to be examined
    BOOL result;                  // results flag
    DWORD readed;                 // discard results
    DWORD ret;
    WORD i;

    DISK_GEOMETRY pdg;
    DWORD sectorSize;
    DWORD signature;
    LARGE_INTEGER diskSize;
    LARGE_INTEGER partSize;
    BYTE actualPartNum;

    DWORD layoutStructSize;
    DRIVE_LAYOUT_INFORMATION_EX* dl;
    CREATE_DISK newDisk;

    actualPartNum = 4;
    if (partNum > actualPartNum)
    {
        return (WORD)-1;
    }

    hDevice = CreateFile(
        diskPath,
        GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,           //default security attributes  
        OPEN_EXISTING, // disposition  
        0,              // file attributes  
        NULL
    );
    if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
    {
        fprintf(stderr, "CreateFile() Error: %ld\n", GetLastError());
        return DWORD(-1);
    }

    // Create primary partition MBR
    newDisk.PartitionStyle = PARTITION_STYLE_MBR;
    signature = (DWORD)time(NULL);     //get signature from current time
    newDisk.Mbr.Signature = signature;

    result = DeviceIoControl(
        hDevice,
        IOCTL_DISK_CREATE_DISK,
        &newDisk,
        sizeof(CREATE_DISK),
        NULL,
        0,
        &readed,
        NULL
    );
    if (!result)
    {
        fprintf(stderr, "IOCTL_DISK_CREATE_DISK Error: %ld\n", GetLastError());
        (void)CloseHandle(hDevice);
        return DWORD(-1);
    }

    //fresh the partition table
    result = DeviceIoControl(
        hDevice,
        IOCTL_DISK_UPDATE_PROPERTIES,
        NULL,
        0,
        NULL,
        0,
        &readed,
        NULL
    );
    if (!result)
    {
        fprintf(stderr, "IOCTL_DISK_UPDATE_PROPERTIES Error: %ld\n", GetLastError());
        (void)CloseHandle(hDevice);
        return DWORD(-1);
    }

    //Now create the partitions
    ret = GetDriveGeometry(diskPath, &pdg);
    if ((DWORD)-1 == ret)
    {
        return ret;
    }
    sectorSize = pdg.BytesPerSector;
    diskSize.QuadPart = pdg.Cylinders.QuadPart * pdg.TracksPerCylinder *
        pdg.SectorsPerTrack * pdg.BytesPerSector;       //calculate the disk size;
    partSize.QuadPart = diskSize.QuadPart / partNum;

    layoutStructSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX) + (actualPartNum - 1) * sizeof(PARTITION_INFORMATION_EX);
    dl = (DRIVE_LAYOUT_INFORMATION_EX*)malloc(layoutStructSize);
    if (NULL == dl)
    {
        (void)CloseHandle(hDevice);
        return (WORD)-1;
    }

    dl->PartitionStyle = (DWORD)PARTITION_STYLE_MBR;
    dl->PartitionCount = actualPartNum;
    dl->Mbr.Signature = signature;

    //clear the unused partitions
    for (i = 0; i < actualPartNum; i++) {
        dl->PartitionEntry[i].RewritePartition = 1;
        dl->PartitionEntry[i].Mbr.PartitionType = PARTITION_ENTRY_UNUSED;
    }
    //set the profile of the partitions
    for (i = 0; i < partNum; i++) {
        dl->PartitionEntry[i].PartitionStyle = PARTITION_STYLE_MBR;
        dl->PartitionEntry[i].StartingOffset.QuadPart =
            (partSize.QuadPart * i) + ((LONGLONG)(pdg.SectorsPerTrack) * (LONGLONG)(pdg.BytesPerSector));   //32256
        dl->PartitionEntry[i].PartitionLength.QuadPart = partSize.QuadPart;
        dl->PartitionEntry[i].PartitionNumber = i + 1;
        dl->PartitionEntry[i].RewritePartition = TRUE;
        dl->PartitionEntry[i].Mbr.PartitionType = PARTITION_ENTRY_UNUSED;
        dl->PartitionEntry[i].Mbr.BootIndicator = FALSE;
        dl->PartitionEntry[i].Mbr.RecognizedPartition = TRUE;
        dl->PartitionEntry[i].Mbr.HiddenSectors =
            pdg.SectorsPerTrack + (DWORD)((partSize.QuadPart / sectorSize) * i);
    }
    //execute the layout  
    result = DeviceIoControl(
        hDevice,
        IOCTL_DISK_SET_DRIVE_LAYOUT_EX,
        dl,
        layoutStructSize,
        NULL,
        0,
        &readed,
        NULL
    );
    if (!result)
    {
        fprintf(stderr, "IOCTL_DISK_SET_DRIVE_LAYOUT_EX Error: %ld\n", GetLastError());
        free(dl);
        (void)CloseHandle(hDevice);
        return DWORD(-1);
    }

    //fresh the partition table
    result = DeviceIoControl(
        hDevice,
        IOCTL_DISK_UPDATE_PROPERTIES,
        NULL,
        0,
        NULL,
        0,
        &readed,
        NULL
    );
    if (!result)
    {
        fprintf(stderr, "IOCTL_DISK_UPDATE_PROPERTIES Error: %ld\n", GetLastError());
        free(dl);
        (void)CloseHandle(hDevice);
        return DWORD(-1);
    }

    free(dl);
    (void)CloseHandle(hDevice);
    Sleep(3000);            //wait the operations take effect
    return 0;
}

DWORD CreateDisk(WORD partNum, LPWSTR diskPath)
{
    HANDLE hDevice;               // handle to the drive to be examined
    BOOL result;                  // results flag
    DWORD readed;                 // discard results
    DWORD ret;
    WORD i;

    DISK_GEOMETRY pdg;
    DWORD sectorSize;
    DWORD signature;
    LARGE_INTEGER diskSize;
    LARGE_INTEGER partSize;
    BYTE actualPartNum = 1;

    DWORD layoutStructSize;
    DRIVE_LAYOUT_INFORMATION_EX* dl;
    CREATE_DISK newDisk;

    actualPartNum = 4;
    //if (partNum > actualPartNum)
    //{
    //    return (WORD)-1;
    //}

    hDevice = CreateFileW(
        diskPath,
        GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,           //default security attributes  
        OPEN_EXISTING, // disposition  
        0,              // file attributes  
        NULL
    );
    if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
    {
        fprintf(stderr, "CreateFile() Error: %ld\n", GetLastError());
        return DWORD(-1);
    }

    // Create primary partition MBR
    newDisk.PartitionStyle = PARTITION_STYLE_MBR;
    signature = rand();     //get signature from current time
    newDisk.Mbr.Signature = signature;

    result = DeviceIoControl(
        hDevice,
        IOCTL_DISK_CREATE_DISK,
        &newDisk,
        sizeof(CREATE_DISK),
        NULL,
        0,
        &readed,
        NULL
    );

    DWORD dwError1 = GetLastError();
    if (!result)
    {
        fprintf(stderr, "IOCTL_DISK_CREATE_DISK Error: %ld\n", GetLastError());
        (void)CloseHandle(hDevice);
        return DWORD(-1);
    }

    //fresh the partition table
    result = DeviceIoControl(
        hDevice,
        IOCTL_DISK_UPDATE_PROPERTIES,
        NULL,
        0,
        NULL,
        0,
        &readed,
        NULL
    );

    DWORD dwError2 = GetLastError();
    if (!result)
    {
        fprintf(stderr, "IOCTL_DISK_UPDATE_PROPERTIES Error: %ld\n", GetLastError());
        (void)CloseHandle(hDevice);
        return DWORD(-1);
    }

    //Now create the partitions
    ret = GetDriveGeometry(diskPath, &pdg);
    if ((DWORD)-1 == ret)
    {
        return ret;
    }
    sectorSize = pdg.BytesPerSector;
    diskSize.QuadPart = pdg.Cylinders.QuadPart * pdg.TracksPerCylinder *
        pdg.SectorsPerTrack * pdg.BytesPerSector;       //calculate the disk size;
    partSize.QuadPart = diskSize.QuadPart / partNum;

    layoutStructSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX) + (actualPartNum - 1) * sizeof(PARTITION_INFORMATION_EX);
    dl = (DRIVE_LAYOUT_INFORMATION_EX*)malloc(layoutStructSize);
    memset(dl, 0, layoutStructSize);
    if (NULL == dl)
    {
        (void)CloseHandle(hDevice);
        return (WORD)-1;
    }

    dl->PartitionStyle = (DWORD)PARTITION_STYLE_MBR;
    dl->PartitionCount = actualPartNum;
    dl->Mbr.Signature = signature;

    //clear the unused partitions
    for (i = 0; i < actualPartNum; i++) {
        dl->PartitionEntry[i].RewritePartition = 1;
        dl->PartitionEntry[i].Mbr.PartitionType = PARTITION_ENTRY_UNUSED;
    }
    //set the profile of the partitions
    for (i = 0; i < partNum; i++) {
        dl->PartitionEntry[i].PartitionStyle = PARTITION_STYLE_MBR;
        dl->PartitionEntry[i].StartingOffset.QuadPart = 
            (partSize.QuadPart * i) + ((LONGLONG)(pdg.SectorsPerTrack) * (LONGLONG)(pdg.BytesPerSector) * 8);   //32256
        dl->PartitionEntry[i].Mbr.HiddenSectors = 4096;
            pdg.SectorsPerTrack + (DWORD)((partSize.QuadPart / sectorSize) * i);

        dl->PartitionEntry[i].PartitionLength.QuadPart = partSize.QuadPart;
        dl->PartitionEntry[i].PartitionNumber = i+1;
        dl->PartitionEntry[i].RewritePartition = TRUE;
        dl->PartitionEntry[i].Mbr.PartitionType = PARTITION_HUGE;
        dl->PartitionEntry[i].Mbr.BootIndicator = FALSE;
        dl->PartitionEntry[i].Mbr.RecognizedPartition = TRUE;
        
    }
    //execute the layout  
    result = DeviceIoControl(
        hDevice,
        IOCTL_DISK_SET_DRIVE_LAYOUT_EX,
        dl,
        layoutStructSize,
        NULL,
        0,
        &readed,
        NULL
    );

    DWORD dwError3 = GetLastError();
    //PrintError(status);
    if (!result)
    {
        printf( "IOCTL_DISK_SET_DRIVE_LAYOUT_EX Error: %ld\n", GetLastError());
        free(dl);
        (void)CloseHandle(hDevice);
        return DWORD(-1);
    }

    //fresh the partition table
    result = DeviceIoControl(
        hDevice,
        IOCTL_DISK_UPDATE_PROPERTIES,
        NULL,
        0,
        NULL,
        0,
        &readed,
        NULL
    );

    DWORD dwError4 = GetLastError();
    if (!result)
    {
        fprintf(stderr, "IOCTL_DISK_UPDATE_PROPERTIES Error: %ld\n", GetLastError());
        free(dl);
        (void)CloseHandle(hDevice);
        return DWORD(-1);
    }

    //DWORD bytesReturned;
    //BOOL bResult = DeviceIoControl(
    //    hDevice,                         // 磁盘句柄
    //    IOCTL_DISK_SET_PARTITION_INFO_EX,    // 控制码
    //    &dl->PartitionEntry[0],                          // 输入缓冲区，分区参数
    //    sizeof(dl->PartitionEntry[0]),                   // 输入缓冲区大小
    //    NULL,                          // 输出缓冲区
    //    0,                             // 输出缓冲区大小
    //    &bytesReturned,                // 返回的字节数
    //    NULL                           // 同步操作
    //);

    //if (bResult) {
    //    wprintf(L"Partition created successfully.\n");
    //}
    //else {
    //    DWORD dwError = GetLastError();
    //    wprintf(L"Failed to create partition. Error: %lu\n", dwError);
    //}

    free(dl);
    (void)CloseHandle(hDevice);
    Sleep(3000);            //wait the operations take effect
    return 0;
}


void InitializeDisk(const wchar_t* devicePath) {
    HANDLE hDisk = CreateFileW(devicePath, GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);

    if (hDisk == INVALID_HANDLE_VALUE) {
        wprintf(L"Failed to open disk. Error: %d\n", GetLastError());
        return;
    }

    CREATE_DISK createDisk;
    createDisk.PartitionStyle = PARTITION_STYLE_MBR; // 使用 MBR 或 GPT 初始化
    createDisk.Mbr.Signature = time(NULL);  // 随机生成磁盘签名

    DWORD bytesReturned;
    BOOL result = DeviceIoControl(
        hDisk,
        IOCTL_DISK_CREATE_DISK,
        &createDisk,
        sizeof(CREATE_DISK),
        NULL,
        0,
        &bytesReturned,
        NULL
    );

    if (result) {
        wprintf(L"Disk initialized successfully.\n");
    }
    else {
        wprintf(L"Failed to initialize disk. Error: %d\n", GetLastError());
    }

    DRIVE_LAYOUT_INFORMATION_EX driveLayout;
    ZeroMemory(&driveLayout, sizeof(driveLayout));
    driveLayout.PartitionStyle = PARTITION_STYLE_MBR;  // 使用 MBR 或 GPT
    driveLayout.Mbr.Signature = rand();  // 随机生成磁盘签名
    driveLayout.PartitionCount = 1;

    PARTITION_INFORMATION_EX partitionInfo;
    partitionInfo.PartitionStyle = PARTITION_STYLE_MBR;
    partitionInfo.StartingOffset.QuadPart = 1048576; // 1MB 偏移（通常是第一个分区的起始位置）
    partitionInfo.PartitionLength.QuadPart = 1024 * 1024 * 1024 * 18; // 100MB 分区
    partitionInfo.Mbr.PartitionType = PARTITION_EXTENDED;
    partitionInfo.Mbr.BootIndicator = FALSE;
    partitionInfo.Mbr.RecognizedPartition = TRUE;
    partitionInfo.Mbr.HiddenSectors = 2048;

    driveLayout.PartitionEntry[0] = partitionInfo;

    DWORD bytesReturned2;
    BOOL result2 = DeviceIoControl(
        hDisk,
        IOCTL_DISK_SET_DRIVE_LAYOUT_EX,
        &driveLayout,
        sizeof(driveLayout),
        NULL,
        0,
        &bytesReturned2,
        NULL
    );

    //const wchar_t* volumePath = L"\\Device\\HarddiskVolume1"; // 替换为实际的设备路径
    //const wchar_t* driveLetter = L"K:";  // 你希望分配的驱动器号
    //BOOL result3 = DefineDosDevice(DDD_RAW_TARGET_PATH, driveLetter, devicePath);


    CloseHandle(hDisk);
}

void FormatVolume(const wchar_t* volumeName) {
    DWORD bytesReturned;
    HANDLE hVolume = CreateFileW(volumeName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);

    if (hVolume == INVALID_HANDLE_VALUE) {
        wprintf(L"Unable to open volume %s. Error: %d\n", volumeName, GetLastError());
        return;
    }
//void FormatVolume(HANDLE hVolume) {
//    DWORD bytesReturned;

    BOOL result = DeviceIoControl(hVolume, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &bytesReturned, NULL);

    if (!result) {
        wprintf(L"Unable to lock volume . Error: %d\n" , GetLastError());
        CloseHandle(hVolume);
        return;
    }

    result = DeviceIoControl(hVolume, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &bytesReturned, NULL);

    if (!result) {
        wprintf(L"Unable to dismount volume Error: %d\n",  GetLastError());
        CloseHandle(hVolume);
        return;
    }

    wchar_t formatCmd[64];
    swprintf_s(formatCmd, sizeof(formatCmd) / sizeof(wchar_t), L"format %s /FS:NTFS /Q /Y", volumeName);

    _wsystem(formatCmd); // 执行命令行格式化操作

    CloseHandle(hVolume);
    wprintf(L"Volume %s formatted successfully.\n", volumeName);
}

void GetPhysicalPath(HANDLE vhdHandle, LPWSTR physicalPath, LONG PathLenght) {
    DWORD pathSize = 0;

    // 第一次调用获取路径长度
    DWORD status = GetVirtualDiskPhysicalPath(vhdHandle, &pathSize, NULL);
    if (status != ERROR_INSUFFICIENT_BUFFER) {
        wprintf(L"Failed to get buffer size. Error: %d\n", status);
        return;
    }

    // 第二次调用获取物理路径
    status = GetVirtualDiskPhysicalPath(vhdHandle, &pathSize, physicalPath);
    if (status == ERROR_SUCCESS) {
        wprintf(L"Virtual disk physical path: %s\n", physicalPath);
    }
    else {
        wprintf(L"Failed to get physical path. Error: %d\n", status);
    }
}


void PrintError(NTSTATUS status) {
    LPWSTR errMsg = NULL;
    FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL, status, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&errMsg, 0, NULL);
    wprintf(L"Error: %s\n", errMsg);
    LocalFree(errMsg);
}

// 获取卷的物理磁盘号
BOOL GetDiskNumberFromVolume(const wchar_t* volumeGuid) {
    HANDLE hVolume = CreateFileW(volumeGuid, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
    if (hVolume == INVALID_HANDLE_VALUE) {
        wprintf(L"Failed to open volume %s. Error: %d\n", volumeGuid, GetLastError());
        return FALSE;
    }

    VOLUME_DISK_EXTENTS diskExtents;
    DWORD bytesReturned = 0;

    // 使用 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS 获取卷所属的磁盘信息
    BOOL result = DeviceIoControl(hVolume, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, &diskExtents, sizeof(diskExtents), &bytesReturned, NULL);
    if (result) {
        wprintf(L"The volume %s is located on disk number %d\n", volumeGuid, diskExtents.Extents[0].DiskNumber);
        CloseHandle(hVolume);
        return TRUE;
    }
    else {
        wprintf(L"Failed to get disk extents for volume %s. Error: %d\n", volumeGuid, GetLastError());
        CloseHandle(hVolume);
        return FALSE;
    }
}

// 使用 FindFirstVolume 和 FindNextVolume 枚举卷并为指定卷分配驱动器号
void ListVolumesAndAssignDriveLetter() {
    WCHAR volumeName[MAX_PATH] = L"";
    HANDLE findHandle = FindFirstVolume(volumeName, ARRAYSIZE(volumeName));

    if (findHandle == INVALID_HANDLE_VALUE) {
        printf("Failed to find volumes. Error: %d\n", GetLastError());
        return;
    }

    do {

        wchar_t volumePathNames[MAX_PATH] = L"";
        DWORD returnLength = 0;
        GetVolumePathNamesForVolumeNameW(volumeName, volumePathNames,
            ARRAYSIZE(volumePathNames), &returnLength);
        wprintf(L"Found volume: %s Path:%s \n", volumeName, volumePathNames);

        GetDiskNumberFromVolume(volumeName);
        // 假设我们为第一个找到的卷分配驱动器号 K:
        //AssignDriveLetter(volumeName, L"K:\\");
        //break;  // 这里只为找到的第一个卷分配驱动器号
        
    } while (FindNextVolume(findHandle, volumeName, ARRAYSIZE(volumeName)));

    FindVolumeClose(findHandle);
}

void ListDrivesWithoutDriveLetter2() {
    // 枚举物理驱动器，格式为 \\.\PhysicalDriveX，其中 X 是驱动器号
    for (int driveNumber = 2; driveNumber < 3; driveNumber++) {
        WCHAR drivePath[MAX_PATH];
        swprintf_s(drivePath, MAX_PATH, L"\\\\.\\PhysicalDrive%d", driveNumber);

        // 打开驱动器
        HANDLE hDrive = CreateFileW(drivePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
        if (hDrive == INVALID_HANDLE_VALUE) {
            // 如果驱动器不存在，则退出
            if (GetLastError() == ERROR_FILE_NOT_FOUND) {
                break; // 停止枚举
            }
            continue; // 其他错误，继续下一个驱动器
        }

        // 获取驱动器的分区布局
        DWORD bytesReturned = 0;
        DRIVE_LAYOUT_INFORMATION_EX* pDriveLayout = (DRIVE_LAYOUT_INFORMATION_EX*)malloc(1024 * sizeof(DRIVE_LAYOUT_INFORMATION_EX));

        if (!DeviceIoControl(hDrive, IOCTL_DISK_GET_DRIVE_LAYOUT_EX, NULL, 0, pDriveLayout, 1024 * sizeof(DRIVE_LAYOUT_INFORMATION_EX), &bytesReturned, NULL)) {
            printf("Failed to get drive layout for %S. Error: %lu\n", drivePath, GetLastError());
            CloseHandle(hDrive);
            free(pDriveLayout);
            continue;
        }

        // 遍历驱动器的每个分区，检查是否有盘符
        BOOL hasDriveLetter = FALSE;
        WCHAR volumeName[MAX_PATH] = L"";
        WCHAR volumePathNames[MAX_PATH] = L"";
        for (DWORD i = 0; i < pDriveLayout->PartitionCount; i++) {
            
            if (pDriveLayout->PartitionStyle == PARTITION_STYLE_MBR)
            {

                //GUID* PartitionId = pDriveLayout->Mbr
                // 构建分区设备路径，例如 \\?\Volume{GUID}\ 的格式
                swprintf_s(volumeName, MAX_PATH, L"\\\\?\\Volume{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\",
                    pDriveLayout->PartitionEntry[i].Mbr.PartitionId.Data1,
                    pDriveLayout->PartitionEntry[i].Mbr.PartitionId.Data2,
                    pDriveLayout->PartitionEntry[i].Mbr.PartitionId.Data3,
                    pDriveLayout->PartitionEntry[i].Mbr.PartitionId.Data4[0],
                    pDriveLayout->PartitionEntry[i].Mbr.PartitionId.Data4[1],
                    pDriveLayout->PartitionEntry[i].Mbr.PartitionId.Data4[2],
                    pDriveLayout->PartitionEntry[i].Mbr.PartitionId.Data4[3],
                    pDriveLayout->PartitionEntry[i].Mbr.PartitionId.Data4[4],
                    pDriveLayout->PartitionEntry[i].Mbr.PartitionId.Data4[5],
                    pDriveLayout->PartitionEntry[i].Mbr.PartitionId.Data4[6],
                    pDriveLayout->PartitionEntry[i].Mbr.PartitionId.Data4[7]);

                if (0 == i)
                {
                    //WCHAR volumeGUID[MAX_PATH] = { 0 };
                    //BOOL result = GetVolumeNameForVolumeMountPointW(L"Q:\\", volumeGUID, MAX_PATH);
                    DWORD returnLength = 0;
                    GetVolumePathNamesForVolumeNameW(volumeName, volumePathNames,
                        ARRAYSIZE(volumePathNames), &returnLength);
                    //int cmp = wcscmp(volumeGUID, volumeName);
                    BOOL result2 = DeleteVolumeMountPointW(volumePathNames);
                    BOOL bRet = SetVolumeMountPointW(L"K:\\",volumeName);
                    DWORD dwError = GetLastError();
                    int a = 0;
                }
            }
            else if (pDriveLayout->PartitionStyle == PARTITION_STYLE_GPT)
            {
                // 构建分区设备路径，例如 \\?\Volume{GUID}\ 的格式
                swprintf_s(volumeName, MAX_PATH, L"\\\\?\\Volume{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\",
                    pDriveLayout->PartitionEntry[i].Gpt.PartitionId.Data1,
                    pDriveLayout->PartitionEntry[i].Gpt.PartitionId.Data2,
                    pDriveLayout->PartitionEntry[i].Gpt.PartitionId.Data3,
                    pDriveLayout->PartitionEntry[i].Gpt.PartitionId.Data4[0],
                    pDriveLayout->PartitionEntry[i].Gpt.PartitionId.Data4[1],
                    pDriveLayout->PartitionEntry[i].Gpt.PartitionId.Data4[2],
                    pDriveLayout->PartitionEntry[i].Gpt.PartitionId.Data4[3],
                    pDriveLayout->PartitionEntry[i].Gpt.PartitionId.Data4[4],
                    pDriveLayout->PartitionEntry[i].Gpt.PartitionId.Data4[5],
                    pDriveLayout->PartitionEntry[i].Gpt.PartitionId.Data4[6],
                    pDriveLayout->PartitionEntry[i].Gpt.PartitionId.Data4[7]);
            }

            // 获取与该分区关联的所有路径（盘符或挂载点）
            DWORD returnLength = 0;
            if (GetVolumePathNamesForVolumeNameW(volumeName, volumePathNames, ARRAYSIZE(volumePathNames), &returnLength)) {
                if (returnLength > 0) {
                    hasDriveLetter = TRUE;
                    //break; // 已经找到盘符，跳过剩下的分区
                }
            }
        }

        // 如果没有盘符，则打印该驱动器
        if (!hasDriveLetter) {
            wprintf(L"Drive %s does not have any assigned drive letters.\n", drivePath);
        }

        // 清理资源
        CloseHandle(hDrive);
        free(pDriveLayout);
    }
}

int CreateVolume()
{
    HANDLE hVolumeManager = CreateFile(
        L"\\\\.\\VolumeManager",      // 卷管理设备路径
        GENERIC_READ | GENERIC_WRITE, // 读写权限
        FILE_SHARE_READ | FILE_SHARE_WRITE, // 共享模式
        NULL,                         // 安全属性
        OPEN_EXISTING,                // 打开现有设备
        0,                            // 文件属性
        NULL                          // 模板文件
    );

    if (hVolumeManager == INVALID_HANDLE_VALUE) {
        // 处理错误
        DWORD dwError = GetLastError();
        wprintf(L"Failed to open Volume Manager. Error: %lu\n", dwError);
        return -1;
    }

    typedef struct _VOLUME_CREATE_INFORMATION {
        ULONG VolumeType;          // 卷的类型（如简单卷、跨区卷等）
        LARGE_INTEGER VolumeSize;  // 卷的大小
        ULONG DiskNumber;          // 创建卷的目标磁盘号
        ULONG PartitionNumber;     // 目标分区号
    } VOLUME_CREATE_INFORMATION;

    // 填充卷创建信息
    VOLUME_CREATE_INFORMATION vci;
    ZeroMemory(&vci, sizeof(vci));

    vci.VolumeType = 0x00000000; // 假设简单卷
    vci.VolumeSize.QuadPart = 10737418240; // 10 GB 卷
    vci.DiskNumber = 0; // 磁盘编号
    vci.PartitionNumber = 1; // 分区编号

    DWORD bytesReturned;
    BOOL bResult = DeviceIoControl(
        hVolumeManager,                // 卷管理器句柄
         0 /*IOCTL_VOLUME_CREATE*/,           // 控制码
        &vci,                          // 输入缓冲区，包含卷创建信息
        sizeof(vci),                   // 输入缓冲区大小
        NULL,                          // 输出缓冲区（可为 NULL）
        0,                             // 输出缓冲区大小
        &bytesReturned,                // 返回的字节数
        NULL                           // 同步操作
    );

    if (bResult) {
        wprintf(L"Volume created successfully.\n");
    }
    else {
        DWORD dwError = GetLastError();
        wprintf(L"Failed to create volume. Error: %lu\n", dwError);
    }

    CloseHandle(hVolumeManager);
}

int main() {
    HANDLE vhdHandle;
    //ListVolumesAndAssignDriveLetter();
    //ListDrivesWithoutDriveLetter2();
    //return 0;
    GUID VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT = { 0xec984aec, 0xa0f9, 0x47e9, 0x90, 0x1f, 0x71, 0x41, 0x5a, 0x66, 0x34, 0x5b };


    // Setup parameters for creating the virtual disk
    VIRTUAL_STORAGE_TYPE storageType = { VIRTUAL_STORAGE_TYPE_DEVICE_VHDX, VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT };

    // 创建虚拟磁盘的参数
    CREATE_VIRTUAL_DISK_PARAMETERS params;
    memset(&params, 0, sizeof(CREATE_VIRTUAL_DISK_PARAMETERS));
    params.Version = CREATE_VIRTUAL_DISK_VERSION_1;
    params.Version1.MaximumSize = 20LL * 1024 * 1024 * 1024;  // 20GB
    params.Version1.BlockSizeInBytes = CREATE_VIRTUAL_DISK_PARAMETERS_DEFAULT_BLOCK_SIZE;
    params.Version1.SectorSizeInBytes = CREATE_VIRTUAL_DISK_PARAMETERS_DEFAULT_SECTOR_SIZE;
    params.Version1.ParentPath = NULL;
    params.Version1.SourcePath = NULL;

    // Create the virtual disk (VHD) file
    NTSTATUS status = CreateVirtualDisk(
        &storageType,
        L"F:\\VirtualDisk\\myVirtualDisk.vhd",   // Path to the VHD file
        VIRTUAL_DISK_ACCESS_ALL,          // Access mask
        NULL,                             // Security descriptor
        CREATE_VIRTUAL_DISK_FLAG_NONE,    // Flags
        0,                                // Provider-specific flags
        &params,
        NULL,                             // Overlapped
        &vhdHandle                        // Handle to the virtual disk
    );

    if (status == ERROR_FILE_EXISTS)
    {
        VIRTUAL_STORAGE_TYPE storageType =
        {
            VIRTUAL_STORAGE_TYPE_DEVICE_VHD,
            VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT
        };

        OPEN_VIRTUAL_DISK_PARAMETERS parameters =
        {
            OPEN_VIRTUAL_DISK_VERSION_1
        };

        parameters.Version1.RWDepth = OPEN_VIRTUAL_DISK_RW_DEPTH_DEFAULT;

        status = ::OpenVirtualDisk(&storageType,
            L"F:\\VirtualDisk\\myVirtualDisk.vhd",
            VIRTUAL_DISK_ACCESS_ALL,
            OPEN_VIRTUAL_DISK_FLAG_NONE,
            &parameters,
            &vhdHandle);


    }
     if (status != ERROR_SUCCESS) {
        PrintError(status);
        return 1;
    }

     GET_VIRTUAL_DISK_INFO diskInfo;
     ULONG sizeUsed = 0;
     ULONG bufferSize = sizeof(diskInfo);

     // 设置查询版本为获取大小信息
     diskInfo.Version = GET_VIRTUAL_DISK_INFO_SIZE;

     status = GetVirtualDiskInformation(
         vhdHandle,
         &bufferSize,
         &diskInfo,
         &sizeUsed
     );
    wprintf(L"Virtual Disk created successfully.\n");

    // Now attach the virtual disk
    ATTACH_VIRTUAL_DISK_PARAMETERS attachParams;
    memset(&attachParams, 0, sizeof(ATTACH_VIRTUAL_DISK_PARAMETERS));
    attachParams.Version = ATTACH_VIRTUAL_DISK_VERSION_1;

    status = AttachVirtualDisk(
        vhdHandle,
        NULL,                             // Security descriptor
        ATTACH_VIRTUAL_DISK_FLAG_PERMANENT_LIFETIME,  // Flags to make the attachment permanent
        0,                                // Provider-specific flags
        &attachParams,
        NULL                              // Overlapped
    );

    if (status != ERROR_SUCCESS) {
        PrintError(status);
        CloseHandle(vhdHandle);
        return 1;
    }

    WCHAR Buffer[MAX_PATH] = { 0 };
    GetPhysicalPath(vhdHandle, Buffer, MAX_PATH);

    //InitializeDisk(Buffer);
    CreateDisk(1, Buffer);
    //CreateDisk2(4,1, Buffer);

    ListDrivesWithoutDriveLetter2();
    //HANDLE hDisk = CreateFileW(Buffer, GENERIC_READ,
    //    FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
    //    OPEN_EXISTING, 0, NULL);

    //DWORD bytesReturned = 0;
    //DRIVE_LAYOUT_INFORMATION_EX* driveLayout = NULL;
    //bufferSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX) + 128 * sizeof(PARTITION_INFORMATION_EX); // 缓冲区大小

    //driveLayout = (DRIVE_LAYOUT_INFORMATION_EX*)malloc(bufferSize);
    //if (!driveLayout) {
    //    wprintf(L"Failed to allocate memory.\n");
    //    return FALSE;
    //}

    //BOOL result = DeviceIoControl(hDisk, IOCTL_DISK_GET_DRIVE_LAYOUT_EX, NULL, 0, driveLayout, bufferSize, &bytesReturned, NULL);
    //if (!result) {
    //    wprintf(L"Failed to get drive layout. Error: %d\n", GetLastError());
    //    free(driveLayout);
    //    return FALSE;
    //}

    //// 枚举分区
    //wprintf(L"Number of partitions: %lu\n", driveLayout->PartitionCount);
    //for (DWORD i = 0; i < driveLayout->PartitionCount; i++) {
    //    PARTITION_INFORMATION_EX partition = driveLayout->PartitionEntry[i];

    //    wprintf(L"Partition %lu:\n", i + 1);
    //    wprintf(L"  Starting Offset: %llu\n", partition.StartingOffset.QuadPart);
    //    wprintf(L"  Partition Length: %llu\n", partition.PartitionLength.QuadPart);
    //    wprintf(L"  Partition Number: %lu\n", partition.PartitionNumber);
    //    wprintf(L"  Partition Type: 0x%02X\n", partition.Mbr.PartitionType);  // MBR 分区类型
    //    wprintf(L"  Bootable: %s\n", partition.Mbr.BootIndicator ? L"Yes" : L"No");
    //    wprintf(L"  Recognized: %s\n\n", partition.Mbr.RecognizedPartition ? L"Yes" : L"No");
    //}

    //free(driveLayout);
    return 0;



    InitializeDisk(Buffer);
    //const wchar_t* driveLetter = L"K:\\";  // 你希望分配的驱动器号
    //const wchar_t* volumeName = L"\\\\?\\Volume{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}\\";  // 卷的 GUID
    //SetVolumeMountPoint(driveLetter, volumeName);
    wprintf(L"Virtual Disk attached successfully.\n");



    // Clean up
    CloseHandle(vhdHandle);

    return 0;
}
